package guijavacommander.lister;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.swing.*;
import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;

/**
 * User: Deady
 * Date: 20.07.2009
 * Time: 10:18:55
 */
public class ListerPanel extends JPanel {


    private static final int LINE_LENGTH = 75; //todo should be configured
    private RandomAccessFile in;
    private byte[] buffer;
    private Log logger = LogFactory.getLog(ListerPanel.class);
    private BinaryTextPane textpanel;
    private JScrollPane comp;
    private int linesNum;


    public ListerPanel() {
        setLayout(new BorderLayout());


        textpanel = new BinaryTextPane();
        comp = new JScrollPane(textpanel);
        comp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        comp.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent e) {
                try {
                    readData(e.getValue()/textpanel.lineH);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        textpanel.repaint();
                    }
                });
            }
        });
        add(comp, BorderLayout.CENTER);

        buffer = new byte[102400];

    }


    public void setSource(File file) {

        linesNum = (int) file.length() / LINE_LENGTH;
        comp.getVerticalScrollBar().setMaximum(linesNum);
        try {
            in = new RandomAccessFile(file, "r");
            readData(0);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void readData(int pos) throws IOException {
        if (in!=null) {
            in.seek(pos*LINE_LENGTH);
            int readen = in.read(buffer, 0, buffer.length);
            for (int i1 = 0; i1 < buffer.length; i1++) {
                int i = buffer[i1];
                if (i<32) {
                    buffer[i1] = ".".getBytes()[0];
                }

            }
            Arrays.fill(buffer, readen, buffer.length, (byte) 32);
        }
    }


    class BinaryTextPane extends JComponent implements Scrollable {
        public int lineH;
        public int maxWidth;


        BinaryTextPane() {
            super();
            setFont(Font.decode(Font.SANS_SERIF));
            lineH = getFontMetrics(getFont()).getHeight();
            maxWidth = getFontMetrics(getFont()).getMaxAdvance();
        }

        @Override
        public void paint(Graphics g) {
            int y = -getY();
            int pos = 0;
            while ((pos+LINE_LENGTH < buffer.length)) {
                String text = new String(buffer, pos, LINE_LENGTH);
                pos += LINE_LENGTH;
                if (text.length()<LINE_LENGTH) {
                    logger.debug("append space");
                    StringBuilder sb = new StringBuilder();
                    for (int i=0; i < LINE_LENGTH - text.length(); i++) {
                        sb.append(" ");
                    }
                    text += sb.toString();
                }
                g.drawString(text, 0, y + lineH);
                y += lineH;
            }
        }

        @Override
        public Dimension getPreferredSize() {
            final Dimension dimension = new Dimension(maxWidth * LINE_LENGTH, (linesNum +2)* lineH);
            return dimension;
        }

        public Dimension getPreferredScrollableViewportSize() {
            return getPreferredSize();
        }

        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return lineH;
        }

        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return lineH*10;
        }

        public boolean getScrollableTracksViewportWidth() {
            return true;
        }

        public boolean getScrollableTracksViewportHeight() {
            return false;
        }

    }


   
}
